﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;

namespace MapEditor.Map_Classes
{
    public class Map
    {
        //Declare map and tile size variables
        public int FrontLayer1Type { get; set; }
        public int FrontLayer1Height { get; set; }
        public int FrontLayer1Width { get; set; }
        public int FrontLayer1TileWidth { get; set; }
        public int FrontLayer1TileHeight { get; set; }

        public int FrontLayer2Type { get; set; }
        public int FrontLayer2Height { get; set; }
        public int FrontLayer2Width { get; set; }
        public int FrontLayer2TileWidth { get; set; }
        public int FrontLayer2TileHeight { get; set; }

        public int FrontLayer3Type { get; set; }
        public int FrontLayer3Height { get; set; }
        public int FrontLayer3Width { get; set; }
        public int FrontLayer3TileWidth { get; set; }
        public int FrontLayer3TileHeight { get; set; }

        public int ScreenLayerType { get; set; }
        public int ScreenLayerHeight { get; set; }
        public int ScreenLayerWidth { get; set; }
        public int ScreenTileWidth { get; set; }
        public int ScreenTileHeight { get; set; }

        public int PlayerLayerType { get; set; }
        public int PlayerLayerHeight { get; set; }
        public int PlayerLayerWidth { get; set; }
        public int PlayerTileWidth { get; set; }
        public int PlayerTileHeight { get; set; }

        public int EnemyLayerType { get; set; }
        public int EnemyLayerHeight { get; set; }
        public int EnemyLayerWidth { get; set; }
        public int EnemyTileWidth { get; set; }
        public int EnemyTileHeight { get; set; }

        public int BackgroundLayer1Type { get; set; }
        public int BackgroundLayer1Height { get; set; }
        public int BackgroundLayer1Width { get; set; }
        public int Background1TileWidth { get; set; }
        public int Background1TileHeight { get; set; }

        public int BackgroundLayer2Type { get; set; }
        public int BackgroundLayer2Height { get; set; }
        public int BackgroundLayer2Width { get; set; }
        public int Background2TileWidth { get; set; }
        public int Background2TileHeight { get; set; }

        public int BackgroundLayer3Type{ get; set; }
        public int BackgroundLayer3Height { get; set; }
        public int BackgroundLayer3Width { get; set; }
        public int Background3TileWidth { get; set; }
        public int Background3TileHeight { get; set; }


        //Declare new layers
        public Layer FrontLayer1;
        public Layer FrontLayer2;
        public Layer FrontLayer3;
        public Layer PlayerLayer;
        public Layer EnemyLayer;
        public Layer ScreenLayer;
        public Layer BackgroundLayer1;
        public Layer BackgroundLayer2;
        public Layer BackgroundLayer3;
        public Layer SolidLayer;

        public List<Rectangle> tileSet = new List<Rectangle>();

        Rectangle bounds;

        public Map(int FrontLayer1Height, int FrontLayer1Width, int FrontLayer1TileHeight, int FrontLayer1TileWidth, int Front1Type, int FrontLayer2Height, int FrontLayer2Width, int FrontLayer2TileHeight, int FrontLayer2TileWidth, int Front2Type, int FrontLayer3Height, int FrontLayer3Width, int FrontLayer3TileHeight, int FrontLayer3TileWidth, int Front3Type, int ScreenLayerHeight,
                int ScreenLayerWidth, int ScreenTileHeight, int ScreenTileWidth, int ScreenType, int PlayerLayerHeight, int PlayerLayerWidth, int PlayerTileHeight, int PlayerTileWidth, int PlayerType, int EnemyLayerHeight, int EnemyLayerWidth, int EnemyTileHeight, int EnemyTileWidth, int EnemyType, int Background1Height,
                int Background1Width, int Back1TileHeight, int Back1TileWidth, int Back1Type, int Background2Height, int Background2Width, int Back2TileHeight, int Back2TileWidth, int Back2type, int Background3Height, int Background3Width, int Back3TileHeight, int Back3TileWidth, int Back3type)
        {
            //Initialize instance variables
            this.FrontLayer1Type = Front1Type;
            this.FrontLayer1Height = FrontLayer1Height;
            this.FrontLayer1Width = FrontLayer1Width;
            this.FrontLayer1TileHeight = FrontLayer1TileHeight;
            this.FrontLayer1TileWidth = FrontLayer1TileWidth;

            this.FrontLayer2Type = Front2Type;
            this.FrontLayer2Height = FrontLayer2Height;
            this.FrontLayer2Width = FrontLayer2Width;
            this.FrontLayer2TileHeight = FrontLayer2TileHeight;
            this.FrontLayer2TileWidth = FrontLayer2TileWidth;

            this.FrontLayer3Type = Front3Type;
            this.ScreenLayerHeight = ScreenLayerHeight;
            this.ScreenLayerWidth = ScreenLayerWidth;
            this.FrontLayer3TileHeight = FrontLayer3TileHeight;
            this.FrontLayer3TileWidth = FrontLayer3TileWidth;

            this.PlayerLayerType = PlayerType;
            this.PlayerLayerHeight = PlayerLayerHeight;
            this.PlayerLayerWidth = PlayerLayerWidth;
            this.PlayerTileHeight = PlayerTileHeight;
            this.PlayerTileWidth = PlayerTileWidth;

            this.EnemyLayerType = EnemyType;
            this.EnemyLayerHeight = EnemyLayerHeight;
            this.EnemyLayerWidth = EnemyLayerWidth;
            this.EnemyTileHeight = EnemyTileHeight;
            this.EnemyTileWidth = EnemyTileWidth;

            this.ScreenLayerType = ScreenType;
            this.ScreenLayerHeight = ScreenLayerHeight;
            this.ScreenLayerWidth = ScreenLayerWidth;
            this.ScreenTileHeight = ScreenTileHeight;
            this.ScreenTileWidth = ScreenTileWidth;

            this.BackgroundLayer1Type = Back1Type;
            this.BackgroundLayer1Height = Background1Height;
            this.BackgroundLayer1Width = Background1Width;
            this.Background1TileHeight = Back1TileHeight;
            this.Background2TileWidth = Back1TileWidth;

            this.BackgroundLayer2Type = Back2type;
            this.BackgroundLayer2Height = Background2Height;
            this.BackgroundLayer2Width = Background2Width;
            this.Background2TileHeight = Back2TileHeight;
            this.Background2TileWidth = Back2TileWidth;

            this.BackgroundLayer3Type = Back3type;
            this.BackgroundLayer3Height = Background3Height;
            this.BackgroundLayer3Width = Background3Width;
            this.Background3TileHeight = Back3TileHeight;
            this.Background3TileWidth = Back3TileWidth;

            //Initialize the layers
            FrontLayer1 = new Layer(FrontLayer1Width, FrontLayer1Height, FrontLayer1TileWidth, FrontLayer1TileHeight);
            FrontLayer2 = new Layer(FrontLayer2Width, FrontLayer2Height, FrontLayer2TileWidth, FrontLayer2TileHeight);
            FrontLayer3 = new Layer(FrontLayer3Width, FrontLayer3Height, FrontLayer3TileWidth, FrontLayer3TileHeight);
            PlayerLayer = new Layer(PlayerLayerWidth, PlayerLayerHeight, PlayerTileWidth, PlayerTileHeight);
            EnemyLayer = new Layer(EnemyLayerWidth, EnemyLayerHeight, EnemyTileWidth, EnemyTileHeight);
            ScreenLayer = new Layer(ScreenLayerWidth, ScreenLayerHeight, ScreenTileWidth, ScreenTileHeight);
            BackgroundLayer1 = new Layer(BackgroundLayer1Width, BackgroundLayer1Height, Back1TileWidth, Back1TileHeight);
            BackgroundLayer2 = new Layer(BackgroundLayer2Width, BackgroundLayer2Height, Back2TileWidth, Back2TileHeight);
            BackgroundLayer3 = new Layer(BackgroundLayer3Width, BackgroundLayer3Height, Back3TileWidth, Back3TileHeight);
        }

        public void UpdateUserInput()
        {
            KeyboardState newState = Keyboard.GetState();

            if(newState.IsKeyDown(Keys.A))
            {
                Game1.drawOffset.X -=1;
            }
            if(newState.IsKeyDown(Keys.D))
            {
                Game1.drawOffset.X +=1;
            }
            if(newState.IsKeyDown(Keys.W))
            {
                Game1.drawOffset.Y -= 1;
            }
            if(newState.IsKeyDown(Keys.S))
            {
                Game1.drawOffset.Y +=1;
            }
        }

        public void SaveMap(String fileName)
        {
            try
            {
                //Declare and initializ the stream write object
                System.IO.StreamWriter objWriter;
                objWriter = new System.IO.StreamWriter(@fileName + ".txt");

                objWriter.WriteLine(FrontLayer1Type);
                objWriter.WriteLine(FrontLayer1Height);
                objWriter.WriteLine(FrontLayer1Width);
                objWriter.WriteLine(FrontLayer1TileHeight);
                objWriter.WriteLine(FrontLayer1TileWidth);

                objWriter.WriteLine(FrontLayer2Type);
                objWriter.WriteLine(FrontLayer2Height);
                objWriter.WriteLine(FrontLayer2Width);
                objWriter.WriteLine(FrontLayer2TileHeight);
                objWriter.WriteLine(FrontLayer2TileWidth);

                objWriter.WriteLine(EnemyLayerType);
                objWriter.WriteLine(EnemyLayerHeight);
                objWriter.WriteLine(EnemyLayerWidth);
                objWriter.WriteLine(FrontLayer3TileHeight);
                objWriter.WriteLine(FrontLayer3TileWidth);

                objWriter.WriteLine(PlayerLayerType);
                objWriter.WriteLine(PlayerLayerHeight);
                objWriter.WriteLine(PlayerLayerWidth);
                objWriter.WriteLine(PlayerTileHeight);
                objWriter.WriteLine(PlayerTileWidth);

                objWriter.WriteLine(ScreenLayerType);
                objWriter.WriteLine(ScreenLayerHeight);
                objWriter.WriteLine(ScreenLayerWidth);
                objWriter.WriteLine(ScreenTileHeight);
                objWriter.WriteLine(ScreenTileWidth);

                objWriter.WriteLine(BackgroundLayer1Type);
                objWriter.WriteLine(BackgroundLayer1Height);
                objWriter.WriteLine(BackgroundLayer1Width);
                objWriter.WriteLine(Background1TileHeight);
                objWriter.WriteLine(Background1TileWidth);

                objWriter.WriteLine(BackgroundLayer2Type);
                objWriter.WriteLine(BackgroundLayer2Height);
                objWriter.WriteLine(BackgroundLayer2Width);
                objWriter.WriteLine(Background2TileHeight);
                objWriter.WriteLine(Background2TileWidth);

                objWriter.WriteLine(BackgroundLayer3Type);
                objWriter.WriteLine(BackgroundLayer3Height);
                objWriter.WriteLine(BackgroundLayer3Width);
                objWriter.WriteLine(Background3TileHeight);
                objWriter.WriteLine(Background3TileWidth);

                //Write the Layers to the text file
                BackgroundLayer3.SaveLayer(objWriter);
                BackgroundLayer2.SaveLayer(objWriter);
                BackgroundLayer1.SaveLayer(objWriter);
                ScreenLayer.SaveLayer(objWriter);
                EnemyLayer.SaveLayer(objWriter);
                PlayerLayer.SaveLayer(objWriter);
                FrontLayer3.SaveLayer(objWriter);
                FrontLayer2.SaveLayer(objWriter);
                FrontLayer1.SaveLayer(objWriter);

                objWriter.Close();
                objWriter.Dispose();
            }
            catch(Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("There was an error saving th map/nError: " + ex);
            }
        }

        public void Loadmap(String loadFileName)
        {
            try
            {
                //Declare and initialize Streamreader Object
                System.IO.StreamReader objReader;
                objReader = new System.IO.StreamReader(@loadFileName);

                //Find the map height and width from file
                FrontLayer1Type = Convert.ToInt32(objReader.ReadLine());
                FrontLayer1Height = Convert.ToInt32(objReader.ReadLine());
                FrontLayer1Width = Convert.ToInt32(objReader.ReadLine());
                FrontLayer1TileHeight = Convert.ToInt32(objReader.ReadLine());
                FrontLayer1TileWidth = Convert.ToInt32(objReader.ReadLine());

                FrontLayer2Type = Convert.ToInt32(objReader.ReadLine());
                FrontLayer2Height = Convert.ToInt32(objReader.ReadLine());
                FrontLayer2Width = Convert.ToInt32(objReader.ReadLine());
                FrontLayer2TileHeight = Convert.ToInt32(objReader.ReadLine());
                FrontLayer2TileWidth = Convert.ToInt32(objReader.ReadLine());

                FrontLayer3Type = Convert.ToInt32(objReader.ReadLine());
                FrontLayer3Height = Convert.ToInt32(objReader.ReadLine());
                FrontLayer3Width = Convert.ToInt32(objReader.ReadLine());
                FrontLayer3TileHeight = Convert.ToInt32(objReader.ReadLine());
                FrontLayer3TileWidth = Convert.ToInt32(objReader.ReadLine());

                EnemyLayerType = Convert.ToInt32(objReader.ReadLine());
                EnemyLayerHeight = Convert.ToInt32(objReader.ReadLine());
                EnemyLayerWidth = Convert.ToInt32(objReader.ReadLine());
                EnemyTileHeight = Convert.ToInt32(objReader.ReadLine());
                EnemyTileWidth = Convert.ToInt32(objReader.ReadLine());

                PlayerLayerType = Convert.ToInt32(objReader.ReadLine());
                PlayerLayerHeight = Convert.ToInt32(objReader.ReadLine());
                PlayerLayerWidth = Convert.ToInt32(objReader.ReadLine());
                PlayerTileHeight = Convert.ToInt32(objReader.ReadLine());
                PlayerTileWidth = Convert.ToInt32(objReader.ReadLine());

                ScreenLayerType = Convert.ToInt32(objReader.ReadLine());
                ScreenLayerHeight = Convert.ToInt32(objReader.ReadLine());
                ScreenLayerWidth = Convert.ToInt32(objReader.ReadLine());
                ScreenTileHeight = Convert.ToInt32(objReader.ReadLine());
                ScreenTileWidth = Convert.ToInt32(objReader.ReadLine());

                BackgroundLayer1Type = Convert.ToInt32(objReader.ReadLine());
                BackgroundLayer1Height = Convert.ToInt32(objReader.ReadLine());
                BackgroundLayer1Width = Convert.ToInt32(objReader.ReadLine());
                Background1TileHeight = Convert.ToInt32(objReader.ReadLine());
                Background1TileWidth = Convert.ToInt32(objReader.ReadLine());

                BackgroundLayer2Type = Convert.ToInt32(objReader.ReadLine());
                BackgroundLayer2Height = Convert.ToInt32(objReader.ReadLine());
                BackgroundLayer2Width = Convert.ToInt32(objReader.ReadLine());
                Background2TileHeight = Convert.ToInt32(objReader.ReadLine());
                Background2TileWidth = Convert.ToInt32(objReader.ReadLine());

                BackgroundLayer3Type = Convert.ToInt32(objReader.ReadLine());
                BackgroundLayer3Height = Convert.ToInt32(objReader.ReadLine());
                BackgroundLayer3Width = Convert.ToInt32(objReader.ReadLine());
                Background3TileHeight = Convert.ToInt32(objReader.ReadLine());
                Background3TileWidth = Convert.ToInt32(objReader.ReadLine());


                FrontLayer1 = new Layer(FrontLayer1Width, FrontLayer1Height, FrontLayer1TileWidth, FrontLayer1TileHeight);
                FrontLayer2 = new Layer(FrontLayer2Width, FrontLayer2Height, FrontLayer2TileWidth, FrontLayer2TileHeight);
                FrontLayer3 = new Layer(FrontLayer3Width, FrontLayer3Height, FrontLayer3TileWidth, FrontLayer3TileHeight);
                EnemyLayer = new Layer(EnemyLayerWidth, EnemyLayerHeight, EnemyTileWidth, EnemyTileHeight);
                PlayerLayer = new Layer(PlayerLayerWidth, PlayerLayerHeight, PlayerTileWidth, PlayerTileHeight);
                ScreenLayer = new Layer(ScreenLayerWidth, ScreenLayerHeight, ScreenTileWidth, ScreenTileHeight);
                BackgroundLayer1 = new Layer(BackgroundLayer1Width, BackgroundLayer1Height, Background1TileWidth, Background1TileHeight);
                BackgroundLayer2 = new Layer(BackgroundLayer2Width, BackgroundLayer2Height, Background2TileWidth, Background2TileHeight);
                BackgroundLayer3 = new Layer(BackgroundLayer3Width, BackgroundLayer3Height, Background3TileWidth, Background3TileHeight);

                BackgroundLayer3.LoadLayer(objReader);
                BackgroundLayer2.LoadLayer(objReader);
                BackgroundLayer1.LoadLayer(objReader);
                ScreenLayer.LoadLayer(objReader);
                EnemyLayer.LoadLayer(objReader);
                PlayerLayer.LoadLayer(objReader);
                FrontLayer3.LoadLayer(objReader);
                FrontLayer2.LoadLayer(objReader);
                FrontLayer1.LoadLayer(objReader);


                objReader.Close();
                objReader.Dispose();
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("There was an error Loading the map./nError: " + ex);
            }
        }

        public void DrawMap()
        {
            try
            {
               
                    //Loop through all tile positions
                    if (Game1.Front1Draw == true)
                    {
                        for (int x = 0; x < FrontLayer1Height; ++x)
                        {
                            for (int y = 0; y < FrontLayer1Width; ++y)
                            {
                                if (FrontLayer1.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[FrontLayer1.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.Front1TileSheet, new Vector2(((y - Game1.drawOffset.X) * FrontLayer1TileWidth), ((x - Game1.drawOffset.Y) * FrontLayer1TileHeight)), bounds, Color.White);
                                }
                            }
                        }
                    }

                    if (Game1.Front2Draw == true)
                    {
                        for (int x = 0; x < FrontLayer2Height; ++x)
                        {
                            for (int y = 0; y < FrontLayer2Width; ++y)
                            {
                                if (FrontLayer2.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[FrontLayer2.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.Front2TileSheet, new Vector2(((y - Game1.drawOffset.X) * FrontLayer2TileWidth), ((x - Game1.drawOffset.Y) * FrontLayer2TileHeight)), bounds, Color.White);
                                }
                            }
                        }
                    }

                    if (Game1.Front2Draw == true)
                    {
                        for (int x = 0; x < FrontLayer3Height; ++x)
                        {
                            for (int y = 0; y < FrontLayer3Width; ++y)
                            {
                                if (FrontLayer2.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[FrontLayer2.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.Front3TileSheet, new Vector2(((y - Game1.drawOffset.X) * FrontLayer3TileWidth), ((x - Game1.drawOffset.Y) * FrontLayer3TileHeight)), bounds, Color.White);
                                }
                            }
                        }
                    }
                    if (Game1.EnemyDraw == true)
                    {
                        for (int x = 0; x < EnemyLayerHeight; ++x)
                        {
                            for (int y = 0; y < EnemyLayerWidth; ++y)
                            {
                                if (EnemyLayer.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[EnemyLayer.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.EnemyTileSheet, new Vector2(((y - Game1.drawOffset.X) * EnemyTileWidth), ((x - Game1.drawOffset.Y) * EnemyTileWidth)), bounds, Color.White);
                                }
                            }
                        }
                    }
                    if (Game1.PlayerDraw == true)
                    {
                        for (int x = 0; x < PlayerLayerHeight; ++x)
                        {
                            for (int y = 0; y < PlayerLayerWidth; ++y)
                            {
                                if (PlayerLayer.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[PlayerLayer.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.PlayerTileSheet, new Vector2(((y - Game1.drawOffset.X) * PlayerTileWidth), ((x - Game1.drawOffset.Y) * PlayerTileHeight)), bounds, Color.White);
                                }
                            }
                        }
                    }
                    if (Game1.ScreenDraw == true)
                    {
                        for (int x = 0; x < ScreenLayerHeight; ++x)
                        {
                            for (int y = 0; y < ScreenLayerWidth; ++y)
                            {
                                if (ScreenLayer.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[ScreenLayer.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.ScreenTileSheet, new Vector2(((y - Game1.drawOffset.X) * ScreenTileWidth), ((x - Game1.drawOffset.Y) * ScreenTileHeight)), bounds, Color.White);
                                }
                            }
                        }
                    }
                    if (Game1.Back1Draw == true)
                    {
                        for (int x = 0; x < BackgroundLayer1Height; ++x)
                        {
                            for (int y = 0; y < BackgroundLayer1Width; ++y)
                            {
                                if (BackgroundLayer1.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[BackgroundLayer1.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.Back1TileSheet, new Vector2(((y - Game1.drawOffset.X) * Background1TileWidth), ((x - Game1.drawOffset.Y) * Background1TileHeight)), bounds, Color.White);
                                }
                            }
                        }
                    }

                    if (Game1.Back2Draw == true)
                    {
                        for (int x = 0; x < BackgroundLayer2Height; ++x)
                        {
                            for (int y = 0; y < BackgroundLayer2Width; ++y)
                            {
                                if (BackgroundLayer2.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[BackgroundLayer2.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.Back2TileSheet, new Vector2(((y - Game1.drawOffset.X) * Background2TileWidth), ((x - Game1.drawOffset.Y) * Background2TileHeight)), bounds, Color.White);
                                }
                            }
                        }
                    }
                    if (Game1.Back3Draw == true)
                    {
                        for (int x = 0; x < BackgroundLayer3Height; ++x)
                        {
                            for (int y = 0; y < BackgroundLayer3Width; ++y)
                            {
                                if (BackgroundLayer3.layer[y, x] != 0)
                                {
                                    //Set the tile 
                                    bounds = tileSet[BackgroundLayer3.layer[y, x] - 1];

                                    //Draw the tile
                                    Game1.spriteBatch.Draw(Game1.Back3TileSheet, new Vector2(((y - Game1.drawOffset.X) * Background3TileWidth), ((x - Game1.drawOffset.Y) * Background3TileHeight)), bounds, Color.White);
                                }
                            }
                        }
                    }
                }
            catch
            {
                //Empty
            }
        }

        public void LoadTileSet(Texture2D tileSheet, int tileWidth, int tileHeight)
        {
            //Get tile dimensions
            int noOfTilesX = (int)tileSheet.Width / tileWidth;
            int noOfTilesY = (int)tileSheet.Height / tileHeight;

            //Initialize tileset list

            tileSet = new List<Rectangle>(noOfTilesX * noOfTilesY);

            //Get bounds of all tiles in sheet
            for (int j = 0; j < noOfTilesY; ++j)
            {
                for (int i = 0; i < noOfTilesX; ++i)
                {
                    bounds = new Rectangle(i * tileWidth, j * tileHeight, tileWidth, tileHeight);
                    tileSet.Add(bounds);
                }
            }
        }

    }
}
